PIC Tutorial Nine - HEX Keypad
For these tutorials you require the Main Board, Keypad Board, LCD
Board, IR Board and RS232 Board. Download
zipped tutorial files.
These tutorials demonstrate how to read a HEX keypad, these are a
standard device with 16 keys connected in a 4x4 matrix, giving the
characters 0-9 and A-F. You can also use a 4x3 keypad, which gives the
numbers 0-9, * and #.
 |
This is how the HEX keypad is connected, each
square with a number or letter in it is a push to make switch, which
connects the horizontal wires (rows) with the vertical wires
(columns). So if you press button 'A' it will connect COL1 with
ROW4, or pressing button '6' will connect COL3 with ROW2. For a
numeric (4x3) keypad COL4 will be missing, and 'A' and 'B' replaced
with '*' and '#' but is otherwise the same. The sample programs use
a lookup table for the keys, this would need to be changed to insert
the correct values for the non-numeric
characters. |
As the switches are all interconnected, we need a way to
differentiate between the different ones - the four resistors on the
interface board pull lines COL1 to COL4 high, these four lines are the
ones which are read in the program. So in the absence of any switch been
pressed these lines will all read high. The four ROW connections are
connected to output pins, and if these are set high the switches will
effectively do nothing - connecting a high level to a high level, results
in a high level.
In order to detect a switch we need to take the ROW lines low, so
if we take all the ROW lines low - what happens?. Assuming we press button
1, this joins COL1 with ROW1, as ROW1 is now at a low level, this will
pull COL1 down resulting in a low reading on COL1. Unfortunately if we
press button 4, this joins COL1 with ROW2, as ROW2 is at a low level this
also results in a low reading at COL1. This would only give us four
possible choices, where each four buttons in a COL do exactly the same
(e.g. 1, 4, 7, and A are the same).
The way round this is to only switch one ROW at a time low, so
assuming we set ROW1 low we can then read just the top row of buttons,
button 1 will take COL1 low, button2 will take COL2 low, and the same for
buttons '3' and 'F' in COL3 and COL4. The twelve lower buttons won't have
any effect as their respective ROW lines are still high. So to read the
other buttons we need to take their respective ROW lines low, taking ROW2
low will allow us to read the second row of buttons (4, 5, 6, and E),
again as the other three ROW lines are now high the other 12 buttons have
no effect. We can then repeat this for the last two ROW's using ROW3 and
ROW4, so we read four buttons at a time, taking a total of four readings
to read the entire keypad - this is a common technique for reading
keyboards, and is called 'Keyboard Scanning'.
One obvious problem is what happens if you press more than one
key at a time?, there are a number of ways to deal with this, one way
would be to check for multiple key presses and ignore them, a simpler way
(and that used in the examples) is to accept the first key you find which
is pressed. You will find that various commercial products deal with this
situation in similar ways, some reject multiple key presses, and some just
accept the first one.
As with previous tutorials, the idea is to give a tested working
routine which can be used elsewhere, the subroutine to be called is
Chk_Keys, the first thing this does is check to see if any of the 12 keys
are pressed (by making all the ROW lines low) and waiting until no keys
are pressed - this avoids problems with key presses repeating. Once no
keys are pressed it jumps to the routine Keys which repeatedly scans the
keyboard until a key is pressed, a call to one of my standard delay
routines (call Delay20) provides a suitable de-bouncing delay. Once a key
has been pressed the result is returned in the variable 'key', this is
then logically ANDed with 0x0F to make absolutely sure it's between 0 and
15. Next this value is passed to a look-up table which translates the key
to it's required value (in this case the ASCII value of the labels on the
keys). Finally the ASCII value is stored back in the 'key' variable (just
in case you might need it storing) and the routine returns with the ASCII
value in the W register.
;Keypad subroutine
Chk_Keys movlw 0x00 ;wait until no key pressed
movwf KEY_PORT ;set all output pins low
movf KEY_PORT, W
andlw 0x0F ;mask off high byte
sublw 0x0F
btfsc STATUS, Z ;test if any key pressed
goto Keys ;if none, read keys
call Delay20
goto Chk_Keys ;else try again
Keys call Scan_Keys
movlw 0x10 ;check for no key pressed
subwf key, w
btfss STATUS, Z
goto Key_Found
call Delay20
goto Keys
Key_Found movf key, w
andlw 0x0f
call Key_Table ;lookup key in table
movwf key ;save back in key
return ;key pressed now in W
Scan_Keys clrf key
movlw 0xF0 ;set all output lines high
movwf KEY_PORT
movlw 0x04
movwf rows ;set number of rows
bcf STATUS, C ;put a 0 into carry
Scan rrf KEY_PORT, f
bsf STATUS, C ;follow the zero with ones
;comment out next two lines for 4x3 numeric keypad.
btfss KEY_PORT, Col4
goto Press
incf key, f
btfss KEY_PORT, Col3
goto Press
incf key, f
btfss KEY_PORT, Col2
goto Press
incf key, f
btfss KEY_PORT, Col1
goto Press
incf key, f
decfsz rows, f
goto Scan
Press return
For the full code, with the equates, variable declarations and
look-up table, consult the code for the examples below.
Tutorial 9.1
Tutorial 9.1 simply reads the keyboard and displays the value of
the key pressed on the LCD module, it shows this as both HEX and ASCII, so
if you press key '0' it will display '30 0'.
Tutorial 9.2
This tutorial implements a simple code lock, you enter a 4 digit
code and it responds on the LCD with either 'Correct Code' or 'Wrong
Code', it uses all sixteen available I/O lines on a 16F628 which leaves no
spare I/O line for opening an electrical lock. However, using a 4x3 keypad
would free one I/O line, or a 16F876 could be used giving plenty of free
I/O. I've set the code length at 4 digits, it could very easily be altered
from this. The secret code is currently stored within the program source
code, as the 16F628 and 16F876 have internal EEPROM the code could be
stored there and be changeable from the keypad.
Tutorial 9.3
Tutorial 9.3 reads the keypad and sends the ASCII code via RS232
at 9600 baud, you can use HyperTerminal on a PC to display the data.
Basically this is the same as 9.1 but uses a serial link to a PC instead
of the LCD screen.
Tutorial 9.4
A common use for keyboard scanning applications, this example
reads the keypad and transmits IR remote control signals to control a Sony
TV, this works in a very similar way to the circuit used in your TV remote
control. The Sony SIRC's system sends all pressed keys repeatedly, so for
this application we "call Keys" rather than "call Chk_Keys" - this
produces a remote which nicely works a Sony TV.
|